<template>
  <el-upload
      ref="fileUpload"
      v-model:file-list="fileList"
      :multiple="multiple"
      :action="uploadFileUrl"
      :before-upload="handleBeforeUpload as any"
      :limit="limit"
      :on-error="handleUploadError"
      :on-exceed="handleExceed"
      :on-success="handleUploadSuccess"
      :on-remove="handleRemove"
      :on-change="handleChange"
      :show-file-list="showFileList"
      :headers="headers"
      :data="params"
      :auto-upload="autoUpload"
  >
    <el-button type="primary" :disabled="disabled" :loading="loading">
      {{ uploadFileButtonName }}
    </el-button>
  </el-upload>
</template>

<script setup lang="ts">
import type {UploadProps, UploadFile, UploadFiles} from 'element-plus'
import {ElMessage} from 'element-plus'
import {reactive} from "vue";
import {getToken} from "@/utils/auth";

interface Props {
  url: string,
  limit?: number | undefined,
  fileSize?: number | undefined,
  multiple?: boolean | undefined,
  uploadFileButtonName?: string,
  fileType: string[],
  params?: any,
  disabled?: boolean | undefined,
  autoUpload?: boolean,
  showFileList?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  url: '',
  limit: 1,
  fileSize: 15,
  multiple: false,
  disabled: false,
  fileType: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf"],
  uploadFileButtonName: '上传',
  params: () => {
  },
  autoUpload: true,
  showFileList: false
})

const emits = defineEmits(['uploadSuccessRes', 'handClickUpload', 'update:file'])
const {
  url,
  limit,
  multiple,
  fileSize,
  fileType,
  disabled,
  uploadFileButtonName,
  params,
  autoUpload,
  showFileList
} = toRefs(props)

const uploadFileUrl = ref(`${import.meta.env.VITE_APP_BASE_URL}${url.value}`)

const headers = reactive({
  Authorization: `Bearer ${getToken()}`
})
const fileUpload = ref()
let fileList = ref([])
let loading = ref(false)

// 上传前校检格式和大小
const handleBeforeUpload: UploadProps['beforeUpload'] = (file: any) => {
  loading.value = true
  // 校检文件类型
  if (fileType.value.length) {
    const fileName = file.name.split('.');
    const fileExt = fileName[fileName.length - 1];
    const isTypeOk = fileType.value.indexOf(fileExt) >= 0;
    if (!isTypeOk) {
      ElMessage.warning({
        message: `文件格式不正确, 请上传${fileType.value.join("/")}格式文件!`
      })
      loading.value = false
      return false;
    }
  }
  // 校检文件大小
  if (fileSize.value) {
    const isLt = file.size / 1024 / 1024 < fileSize.value;
    if (!isLt) {
      ElMessage.error({
        message: `上传文件大小不能超过 ${fileSize.value} MB!`
      })
      loading.value = false
      return false;
    }
  }
  return true;
}
// 文件个数超出
const handleExceed: UploadProps['onExceed'] = () => {
  loading.value = false
  ElMessage.error({
    message: `上传文件数量不能超过 ${limit.value} 个!`
  })
}
// 上传失败
const handleUploadError: UploadProps['onError'] = (error: any) => {
  loading.value = false
  ElMessage.error({
    message: `上传文件失败：${JSON.parse(error.message).message}`,
    duration: 4000
  })
}
// 上传成功回调
const handleUploadSuccess: UploadProps['onSuccess'] = (res, file) => {
  if (res.code === 200) {
    fileList.value = []
    loading.value = false
    ElMessage.success({
      message: '文件上传成功'
    })
    emits('uploadSuccessRes', res.data)
  } else {
    fileList.value = []
    loading.value = false
    ElMessage.error({
      message: res.message
    })
  }
}
const handleChange: UploadProps['onChange'] = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  if (!autoUpload.value) {
    const Files = uploadFiles.map(item => item.raw)
    if (multiple.value) {
      emits('update:file', Files)
    } else {
      emits('update:file', Files[0])
    }
  }
}
const handleRemove: UploadProps['onRemove'] = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  if (!autoUpload.value) {
    const Files = uploadFiles.map(item => item.raw)
    if (multiple.value) {
      emits('update:file', Files)
    } else {
      emits('update:file', Files)
    }
  }
}
defineExpose({fileList})
</script>

<style lang="scss" scoped>

</style>
